﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Syngine.Components.ParticleSystems
{
	/// <summary>
	/// 
	/// </summary>
	public class Particle : IDraw, IUpdate
	{
		#region Fields

		private static Texture2D _texture;
		private Rectangle _rectangle;

		#endregion

		#region Constructors

		/// <summary>
		/// 
		/// </summary>
		public Particle()
		{
			StartAlpha = 255f;
			EndAlpha = 0f;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="position"></param>
		/// <param name="velocity"></param>
		protected Particle(Vector2 position, Vector2 velocity) : this(null, position, velocity)
		{
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="texture"></param>
		/// <param name="position"></param>
		/// <param name="velocity"></param>
		protected Particle(Texture2D texture, Vector2 position, Vector2 velocity)
		{
			_texture = texture;
			StartPosition = position;
			Position = position;
			Velocity = velocity;
		}

		#endregion

		#region Properties

		/// <summary>
		/// 
		/// </summary>
		public Vector2 StartPosition { get; set; }

		/// <summary>
		/// 
		/// </summary>
		public float DefaultWidth { get; set; }

		/// <summary>
		/// 
		/// </summary>
		public float DefaultHeight { get; set; }

		/// <summary>
		/// 
		/// </summary>
		public bool UseDefaults { get; set; }

		/// <summary>
		/// 
		/// </summary>
		public float LifeTime { get; set; }

		/// <summary>
		/// The current rotation of the particle.
		/// </summary>
		public float Rotation { get; set; }

		/// <summary>
		/// The current deceleration of the particle.
		/// </summary>
		public Vector2 Direction { get; set; }

		/// <summary>
		/// The current mass of the particle.
		/// </summary>
		public float Mass { get; set; }

		/// <summary>
		/// The current acceleration of the particle.
		/// </summary>
		public Vector2 Acceleration { get; set; }

		/// <summary>
		/// The current velocity of the particle.
		/// </summary>
		public Vector2 Velocity { get; set; }

		/// <summary>
		/// The current rotation speed of the particle.
		/// </summary>
		public float RotationSpeed { get; set; }

		/// <summary>
		/// The current position of the particle.
		/// </summary>
		public Vector2 Position { get; set; }

		/// <summary>
		/// 
		/// </summary>
		public bool IsDead { get; private set; }

		public int DrawOrder { get; set; }

		public bool Visible { get; set; }

		public bool IsInitialized { get; set; }

		public float CurrentAlpha { get; set; }

		public float StartAlpha { get; set; }

		public float EndAlpha { get; set; }

		protected Rectangle Rectangle
		{
			get
			{
				return _rectangle;
			}
		}

		protected Vector2 Origin { get; set; }

		#endregion

		#region Methods

		public void Initialize()
		{
		}

		public void LoadContent(LoadContext context)
		{
			DefaultWidth = 1.0f;
			DefaultHeight = 1.0f;
			Origin = new Vector2(DefaultWidth / 2, DefaultHeight / 2);

			if (_texture == null)
			{
				_texture = context.Load<Texture2D>("SmokeParticle");
				//_texture = new Texture2D(context.GraphicsDevice, (int)DefaultWidth, (int)DefaultHeight, false, SurfaceFormat.Color);
				//_texture.SetData(new[] { Color.White }, 0, _texture.Width * _texture.Height);
			}

			if (Position == Vector2.Zero)
			{
				Position = StartPosition;
			}
		}

		public void Update(UpdateContext context)
		{
			LifeTime -= (float)context.GameTime.ElapsedGameTime.TotalSeconds;

			if (LifeTime > 0.0f)
			{
				Acceleration = new Vector2(Acceleration.X - Mass, Acceleration.Y - Mass);
				Velocity += GetVelocity(context.GameTime);
				Position += Velocity * Direction;
				Rotation = Rotation += RotationSpeed;
				_rectangle = new Rectangle((int)Position.X, (int)Position.Y,
					UseDefaults ? (int)DefaultWidth : _texture.Bounds.Width,
					UseDefaults ? (int)DefaultHeight : _texture.Bounds.Height
				);
			}
			else
			{
				IsDead = true;
			}
		}

		public void UnloadContent()
		{

		}

		public void Draw(DrawContext context)
		{
			var min = StartAlpha > EndAlpha ? EndAlpha : StartAlpha;
			var max = StartAlpha < EndAlpha ? EndAlpha : StartAlpha;
			CurrentAlpha = MathHelper.Clamp(LifeTime/75, min, max);
			context.Draw(_texture, _rectangle, null, Color.White * CurrentAlpha, Rotation, Origin, SpriteEffects.None, 1f);
		}

		private Vector2 GetVelocity(GameTime gameTime)
		{
			return Acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;
		}

		#endregion
	}
}